package ch.unisi.inf.java.project.riskbami.view;

import ch.unisi.inf.java.project.riskbami.model.*;
import java.awt.Container;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JLabel;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.JRadioButton;
import java.io.*;
import javax.swing.*;
import java.util.HashMap;
import java.util.ArrayList;
import java.awt.Color;


/**
 * SetupFrame make the player set up his game
 * 
 * @author minellir@lu.unisi.ch
 * @author babazadm@lu.unisi.ch
 */
public final class SetupFrame extends JFrame
{
    private ImageIcon map;
    private BufferedImage bufferedMap;
    private HashMap<Color, String> colorsToCountry;
    private Raster pixelMatrix;
    private MapLoader mapLoader;
    private static final JFileChooser fileChooser = new JFileChooser(System.getProperty("user.dir"));
    private JTextField loadMap;
    private final JButton colorb1, colorb2, colorb3, colorb4, colorb5, colorb6;
    private final JTextField loadFile;
    private final Color[] colors;
    private JPanel colorPanel;
    private final JFrame frame;
    private final JTextField firstPlayer, secondPlayer, thirdPlayer, fourthPlayer, fifthPlayer, sixthPlayer;
    private final JRadioButton[][] allTheStatus = new JRadioButton[6][3];
    private final ButtonGroup[] buttonGroups = new ButtonGroup[6];
    
    /**
     * Constructor for the class SetupFrame.
     */
    public SetupFrame() {
        frame = new JFrame("RiskBaMi Setup");
        frame.setResizable(false);
        final Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        colors = new Color[6];
        colors[0] = Color.RED;
        colors[1] = Color.YELLOW;
        colors[2] = Color.ORANGE;
        colors[3] = Color.GREEN;
        colors[4] = Color.BLUE;
        colors[5] = Color.PINK;
        
        //New panel for players added to the window
        final JPanel playerPanel = new JPanel();
        playerPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Player Setups"));
        
        
        contentPane.add(playerPanel, BorderLayout.WEST);
        
        //New panel to handle the south part of the window
        final JPanel southPanel = new JPanel();
        southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.Y_AXIS));
        contentPane.add(southPanel, BorderLayout.SOUTH);
        
        //Northplayerpanel
        final JPanel northPlayerPanel = new JPanel();
        final JLabel playerLabel = new JLabel("Enter the name of the players, click on a color to change it");
        northPlayerPanel.add(playerLabel);
        contentPane.add(northPlayerPanel, BorderLayout.NORTH);
        
        //Panel to load the map
        final JPanel mapPanel = new JPanel();
        mapPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Map selection"));
        GridLayout buttomLayout = new GridLayout(2,2);
        buttomLayout.setVgap(4);
        mapPanel.setLayout(buttomLayout);
        southPanel.add(mapPanel, BorderLayout.WEST);
        
        //Creates the textFields for the MapPanel
        loadMap = new JTextField(20);
        loadMap.setEditable(false);
        loadFile = new JTextField(20);
        loadFile.setEditable(false);
        
        //Panel for the start button
        final JPanel playButtonPanel = new JPanel(new BorderLayout());
        final JPanel buttonPanel = new JPanel();
        playButtonPanel.add(buttonPanel, BorderLayout.EAST);
        southPanel.add(playButtonPanel);
            
        //Buttons
        final JButton startGame = new JButton("Play RiskBaMi!");
        startGame.addActionListener(new StartGameListener(this));
        buttonPanel.add(startGame, BorderLayout.EAST);
        
        final JPanel buttonPanel2 = new JPanel();
        final JButton back = new JButton("Back To Menu");
        buttonPanel2.add(back);
        back.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {frame.setVisible(false);
                                                        back();}
        });
        playButtonPanel.add(buttonPanel2, BorderLayout.WEST);
        
        //Color buttons 
        colorb1 = new JButton();
        colorb1.setBorderPainted(false);
        colorb1.setFocusable(false);
        colorb1.setBackground(colors[0]);
        colorb1.addActionListener(new ColorListener(this, colors[0], 0));
        
        colorb2 = new JButton();
        colorb2.setBorderPainted(false);
        colorb2.setFocusable(false);
        colorb2.setBackground(colors[1]);
        colorb2.addActionListener(new ColorListener(this, colors[1], 1));
        
        colorb3 = new JButton();
        colorb3.setBorderPainted(false);
        colorb3.setFocusable(false);
        colorb3.setBackground(colors[2]);
        colorb3.addActionListener(new ColorListener(this, colors[2], 2));
        
        colorb4 = new JButton();
        colorb4.setBorderPainted(false);
        colorb4.setFocusable(false);
        colorb4.setBackground(colors[3]);
        colorb4.addActionListener(new ColorListener(this, colors[3], 3));
        
        colorb5 = new JButton();
        colorb5.setBorderPainted(false);
        colorb5.setFocusable(false);
        colorb5.setBackground(colors[4]);
        colorb5.addActionListener(new ColorListener(this, colors[4], 4));
        
        colorb6 = new JButton();
        colorb6.setBorderPainted(false);
        colorb6.setFocusable(false);
        colorb6.setBackground(colors[5]);
        colorb6.addActionListener(new ColorListener(this, colors[5], 5));
        
        //panel for the text field of the players' names
        final JPanel namePanel = new JPanel();
        GridLayout namePanelGridLayout = new GridLayout(6, 1);
        GridLayout statusPanelGridLayout = new GridLayout(6, 4);
        namePanelGridLayout.setVgap(11);
        namePanelGridLayout.setHgap(20);
        statusPanelGridLayout.setVgap(6);
        statusPanelGridLayout.setHgap(5);
        namePanel.setLayout(namePanelGridLayout);
        final JPanel statusPanel = new JPanel();
        statusPanel.setLayout(statusPanelGridLayout);
        playerPanel.add(namePanel);
        playerPanel.add(statusPanel, BorderLayout.EAST);
        
        //Text fields of the 6 players
        firstPlayer = new JTextField(15);
        secondPlayer = new JTextField(15);
        thirdPlayer = new JTextField(15);
        fourthPlayer = new JTextField(15);
        fifthPlayer = new JTextField(15);
        sixthPlayer = new JTextField(15);
        
        for(int i = 0; i < allTheStatus.length; i++){
                allTheStatus[i][0] = new JRadioButton("Human");
                allTheStatus[i][1] = new JRadioButton("CPU");
                allTheStatus[i][2] = new JRadioButton("None", true);
                allTheStatus[i][0].setActionCommand("Human");
                allTheStatus[i][1].setActionCommand("CPU");
                allTheStatus[i][2].setActionCommand("None");
                buttonGroups[i] = new ButtonGroup();
                buttonGroups[i].add(allTheStatus[i][0]);
                buttonGroups[i].add(allTheStatus[i][1]);
                buttonGroups[i].add(allTheStatus[i][2]);
            }
        
        namePanel.add(firstPlayer);
        statusPanel.add(colorb1);
        statusPanel.add(allTheStatus[0][0]);
        statusPanel.add(allTheStatus[0][1]);
        statusPanel.add(allTheStatus[0][2]);
        namePanel.add(secondPlayer);
        statusPanel.add(colorb2);
        statusPanel.add(allTheStatus[1][0]);
        statusPanel.add(allTheStatus[1][1]);
        statusPanel.add(allTheStatus[1][2]);
        namePanel.add(thirdPlayer);
        statusPanel.add(colorb3);
        statusPanel.add(allTheStatus[2][0]);
        statusPanel.add(allTheStatus[2][1]);
        statusPanel.add(allTheStatus[2][2]);
        namePanel.add(fourthPlayer);
        statusPanel.add(colorb4);
        statusPanel.add(allTheStatus[3][0]);
        statusPanel.add(allTheStatus[3][1]);
        statusPanel.add(allTheStatus[3][2]);
        namePanel.add(fifthPlayer);
        statusPanel.add(colorb5);
        statusPanel.add(allTheStatus[4][0]);
        statusPanel.add(allTheStatus[4][1]);
        statusPanel.add(allTheStatus[4][2]);
        namePanel.add(sixthPlayer);
        statusPanel.add(colorb6);
        statusPanel.add(allTheStatus[5][0]);
        statusPanel.add(allTheStatus[5][1]);
        statusPanel.add(allTheStatus[5][2]);
        
        //Filechooser Button
        final JButton mapChooser = new JButton("Select Map Image");
        mapChooser.addActionListener(new MapChooserListener(this));
        final JButton textChooser = new JButton("Select Map File .txt");
        textChooser.addActionListener(new TextChooserListener(this));
        
        //add the filechooser to the frame
       mapPanel.add(loadMap);
       mapPanel.add(mapChooser);
       mapPanel.add(loadFile);
       mapPanel.add(textChooser);
            
        //Make it visible
        frame.pack();
        frame.setVisible(true);
    }
    
    /**
     * Goes back to the PreRiskFrame.
     */
    private final void back()
    { 
        new PreRiskFrame();
    }
    
    /**
     * Updates the colors of the player's choose color button
     */
    private final void updateColors(){ 
        colorb1.setBackground(colors[0]);
        colorb2.setBackground(colors[1]);
        colorb3.setBackground(colors[2]);
        colorb4.setBackground(colors[3]);
        colorb5.setBackground(colors[4]);
        colorb6.setBackground(colors[5]);
    }
            
    
    /**
     * Looking at what has been inputted by the user, this method computes the players that want to play risk.
     */
     private final ArrayList<Player> computePlayersFromGUI(){
        final String[] names = new String[] {firstPlayer.getText(), secondPlayer.getText(), thirdPlayer.getText(), fourthPlayer.getText(), fifthPlayer.getText(), sixthPlayer.getText()};
        final ArrayList<Player> players = new ArrayList<Player>(); 
        for(int i = 0; i < buttonGroups.length; i++){
            final String status = buttonGroups[i].getSelection().getActionCommand();
            if(!status.equals("None") && names[i].length() != 0){
                if(status.equals("Human")){
                    players.add(new Human(names[i], colors[i]));
                } else if(status.equals("CPU")){
                    players.add(new AI(names[i], colors[i]));
                }
            }
        }
        
        return players;
     }
    
    //Setters
    /**
     * Set the color of the player
     */
    private final void setPlayerColor(final Color color, final int number) {
        colors[number] = color;
    }
    
    /**
     * Set the text that contains the path of the map.
     */
    private final void setMapLoadText(final String text) {
        loadMap.setText(text);
    }
    
    /**
     * Set the text that contains the path of the file associated with the map.
     */
    private final void setFileLoadText(final String text) {
        loadFile.setText(text);
    }
    
    /**
     * Set the raster for this map.
     */
    public final void setPixelMatrix(final Raster pixelMatrix) {
        this.pixelMatrix = pixelMatrix;
    }
    
    /**
     * Set the map loader that's going to load the map.
     */
    private final void setMapLoader(final MapLoader mapLoader) {
        this.mapLoader = mapLoader;
    }
    
    /**
     * Closes the frame.
     */
    private final void close(){
        frame.setVisible(false);
    }
        
    //Inner classes for some buttons
    /**
     * Listens when the button to choose the map is clicked.
     */
    private final class MapChooserListener implements ActionListener{
        private final SetupFrame frame;
            private MapChooserListener(final SetupFrame frame){
                this.frame = frame;
            }
            
            public final void actionPerformed(final ActionEvent e) {
                final MapLoader mapLoader = new MapLoader(frame);
                map = mapLoader.getImage();
                bufferedMap = mapLoader.getBufferedMap();
                frame.setMapLoadText(mapLoader.getPath());
            }
    }
    
    /**
     * Listens when the button to choose the file associated with the map is clicked.
     */
    private final class TextChooserListener implements ActionListener{
        private final SetupFrame frame;
            private TextChooserListener(final SetupFrame frame){
                this.frame = frame;
            }
            
            public final FileInputStream getFile()
            {
                final int returnVal = fileChooser.showOpenDialog(null);

                if(returnVal != JFileChooser.APPROVE_OPTION) {
                    return null;  // cancelled
                }
                final File selectedFile = fileChooser.getSelectedFile();
                final String lol = selectedFile.getPath();
                frame.setFileLoadText(lol);
                try{
                    final FileInputStream file = new FileInputStream(lol);
                    return file;
                }
                catch(final IOException exc) {
                    return null;
                }   
            }
            public final void actionPerformed(final ActionEvent e) {
                final CountryColorReader colorReader = new CountryColorReader();
                final FileInputStream file = getFile();
                colorsToCountry = colorReader.getFileAsHashmap(file);     
            }
    }
    
    /**
     * Listens when the button to start the game is clicked.
     */
    private final class StartGameListener implements ActionListener{
         private final SetupFrame frame;
            private StartGameListener(final SetupFrame frame){
                this.frame = frame;
            }
            
            public final void actionPerformed(final ActionEvent e) {
                final ArrayList<Player> players = computePlayersFromGUI();
                if(players.size() >= 2){
                        try{
                            final Game game = new Game(players);
                            final RiskFrame gFrame = new RiskFrame(game, map, pixelMatrix, colorsToCountry, bufferedMap);
                            close();
                        } catch (final NullPointerException ex){
                            JOptionPane.showMessageDialog(frame,"No valid file selected!", "RiskBaMi - Setup warning",JOptionPane.WARNING_MESSAGE);}
                } else {
                    JOptionPane.showMessageDialog(frame,"Not enough valid players defined!", "RiskBaMi - Setup warning",JOptionPane.WARNING_MESSAGE);
                }
            }
    }
    
    /**
     * Listens when the button to choose the color is clicked. It creates a new frame to choose a color (JColorChooser).
     */
    private final class ColorListener implements ActionListener{
         private final SetupFrame frame;
         private final Color color;
         private final int number;
            private ColorListener(final SetupFrame frame, final Color color, final int number){
                this.frame = frame;
                this.color = color;
                this.number = number;
            }
            
            public final void actionPerformed(final ActionEvent e) {
                final Color background = JColorChooser.showDialog(null, "RiskBaMi - Choose your color", color);
                frame.setPlayerColor(background, number);
                updateColors();
            }
    }
}
